package cleanstarxchange.server;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;

public class DataStore 
{
	// The Persistent Manager
	PersistenceManager pm;
	
	/**
	 * Constructor for DataStore class. Get instance of PersistanceManager to make changes
	 * to Google DataStore
	 */
	public DataStore()
	{
		pm = PMF.get().getPersistenceManager();
	}
	
	/**
	 * Initialise 50 Celebrity stocks and give them hard-coded prices
	 */
	public void initialize()
	{
		
		// Create a price list for all the stocks
		ArrayList<Double> pl = new ArrayList<Double>(); 
		pl.add(120.3);
		pl.add(119.3);
		pl.add(120.4);
		pl.add(121.3);
		pl.add(122.7);
		
		// Create Stock objects
		Stock a = new Stock( "Angelina Jolie", "AJO", new Long(1), 90.0, pl );
		Stock b = new Stock( "Brad Pitt", "BPI", new Long(2), 90.0, pl );
		Stock c = new Stock( "Clint Eastwood", "CEA", new Long(3), 80.0, pl );
		Stock d = new Stock( "Daniel Craig", "DCR", new Long(4), 100.0, pl );
		Stock e = new Stock( "Drew Barrymore", "DBA", new Long(5), 90.0, pl );
		Stock f = new Stock( "George Clooney", "GCL", new Long(6), 100.0, pl );
		Stock g = new Stock( "Halle Berry", "HBE", new Long(7), 110.0, pl );
		Stock h = new Stock( "Jessica Alba", "JAL", new Long(8), 90.0, pl );
		Stock i = new Stock( "Jim Carrey", "JCA", new Long(9), 80.0, pl );
		Stock j = new Stock( "Tom Cruise", "TCR", new Long(10), 105.0, pl );
		Stock k = new Stock( "Al Pacino", "APA", new Long(11), 105.0, pl );
		Stock l = new Stock( "Tom Hanks", "THA", new Long(12), 105.0, pl );
		Stock m = new Stock( "Matt Damon", "MDA", new Long(13), 105.0, pl );
		Stock n = new Stock( "Renee Zellweger", "RZE", new Long(14), 105.0, pl );
		Stock o = new Stock( "Nicole Kidman", "NKI", new Long(15), 105.0, pl );
		Stock p = new Stock( "Ben Affleck", "BAF", new Long(16), 105.0, pl );
		Stock q = new Stock( "Kate Beckinsdale", "KBE", new Long(17), 105.0, pl );
		Stock r = new Stock( "Nicolas Cage", "NCA", new Long(18), 105.0, pl );
		Stock s = new Stock( "Neve Campbell", "NCM", new Long(19), 105.0, pl );
		Stock t = new Stock( "Jennifer Lopez", "JLO", new Long(20), 105.0, pl );
		Stock u = new Stock( "Katie Holmes", "KHO", new Long(21), 105.0, pl );
		Stock v = new Stock( "Arnold Schwarzenegger", "ASC", new Long(22), 105.0, pl );
		Stock w = new Stock( "Mara Wilson", "MWI", new Long(23), 105.0, pl );
		Stock x = new Stock( "Jennifer Aniston", "JAN", new Long(24), 105.0, pl );
		Stock y = new Stock( "Julianne Moore", "JMO", new Long(25), 105.0, pl );
		Stock z = new Stock( "Emma Watson", "EWA", new Long(26), 105.0, pl );
		Stock aa = new Stock( "Leonardo DiCaprio", "LDI", new Long(27), 105.0, pl );
		Stock bb = new Stock( "Jennifer Love Hewitt", "JLH", new Long(28), 105.0, pl );
		Stock cc = new Stock( "Joseph Gordon-Levitt", "JGL", new Long(29), 105.0, pl );
		Stock dd = new Stock( "Johnny Depp", "JDE", new Long(30), 105.0, pl );
		Stock ee = new Stock( "Will Smith", "WSM", new Long(31), 105.0, pl );
		Stock ff = new Stock( "Paris Hilton", "PHI", new Long(32), 105.0, pl );
		Stock gg = new Stock( "Keanu Reeves", "KRE", new Long(33), 105.0, pl );
		Stock hh = new Stock( "Adam Sandler", "ASA", new Long(34), 105.0, pl );
		Stock ii = new Stock( "Harrison Ford", "HFO", new Long(35), 105.0, pl );
		Stock jj = new Stock( "Mel Gibson", "MGI", new Long(36), 105.0, pl );
		Stock kk = new Stock( "Robin Williams", "RWI", new Long(37), 105.0, pl );
		Stock ll = new Stock( "Jackie Chan", "JCH", new Long(38), 105.0, pl );
		Stock mm = new Stock( "Eddie Murphy", "EMU", new Long(39), 105.0, pl );
		Stock nn = new Stock( "Mike Myers", "MMY", new Long(40), 105.0, pl );
		Stock oo = new Stock( "Sandra Bullock", "SBU", new Long(41), 105.0, pl );
		Stock pp = new Stock( "Cameron Diaz", "CDI", new Long(42), 105.0, pl );
		Stock qq = new Stock( "Meg Ryan", "MRY", new Long(43), 105.0, pl );
		Stock rr = new Stock( "Catherine Zeta-Jones", "CZJ", new Long(44), 105.0, pl );
		Stock ss = new Stock( "Chris Tucker", "CTU", new Long(45), 105.0, pl );
		Stock tt = new Stock( "Beyonce Knowles", "BKN", new Long(46), 105.0, pl );
		Stock uu = new Stock( "Zac Efron", "ZEF", new Long(47), 105.0, pl );
		Stock vv = new Stock( "Claire Danes", "CDA", new Long(48), 105.0, pl );
		Stock ww = new Stock( "Jessica Biel", "JBI", new Long(49), 105.0, pl );
		Stock xx = new Stock( "Kristen Stewart", "KST", new Long(50), 105.0, pl );
		Stock zz = new Stock( "Britney Spears", "BSP", new Long(51), 105.0, pl );
		Stock aaa = new Stock ("Katy Perry", "KPR", new Long(52), 105.0, pl );
		Stock bbb = new Stock ("Ke$ha", "KSH", new Long(53), 105.0, pl );
		Stock ccc = new Stock ("Rihanna", "RNA", new Long(54), 105.0, pl );
		Stock ddd = new Stock ("David Guetta", "DGA", new Long(55), 105.0, pl );
		Stock eee = new Stock ("Usher", "USH", new Long(56), 105.0, pl );
		Stock fff = new Stock ("Justin Timberlake", "JTR", new Long(57), 105.0, pl );
		Stock ggg = new Stock ("Justin Bieber", "JBR", new Long(58), 105.0, pl );
		Stock hhh = new Stock ("Taylor Lautner", "TLR", new Long(59), 105.0, pl );
		Stock iii = new Stock ("Robert Pattinson", "RPN", new Long(60), 105.0, pl );
		Stock jjj = new Stock ("Lady Gaga", "LGG", new Long(61), 105.0, pl );
		
		// Add all the Stock objects into the Google DataStore
		pm.makePersistent(a);
		pm.makePersistent(b);
		pm.makePersistent(c);
		pm.makePersistent(d);
		pm.makePersistent(e);
		pm.makePersistent(f);
		pm.makePersistent(g);
		pm.makePersistent(h);
		pm.makePersistent(i);
		pm.makePersistent(j);
		pm.makePersistent(k);
		pm.makePersistent(l);
		pm.makePersistent(m);
		pm.makePersistent(n);
		pm.makePersistent(o);
		pm.makePersistent(p);
		pm.makePersistent(q);
		pm.makePersistent(r);
		pm.makePersistent(s);				
		pm.makePersistent(t);
		pm.makePersistent(u);
		pm.makePersistent(v);
		pm.makePersistent(w);
		pm.makePersistent(x);
		pm.makePersistent(y);
		pm.makePersistent(z);
		pm.makePersistent(aa);
		pm.makePersistent(bb);
		pm.makePersistent(cc);
		pm.makePersistent(dd);
		pm.makePersistent(ee);
		pm.makePersistent(ff);
		pm.makePersistent(gg);
		pm.makePersistent(hh);
		pm.makePersistent(ii);
		pm.makePersistent(jj);
		pm.makePersistent(kk);
		pm.makePersistent(ll);
		pm.makePersistent(mm);
		pm.makePersistent(nn);
		pm.makePersistent(oo);
		pm.makePersistent(pp);
		pm.makePersistent(qq);
		pm.makePersistent(rr);
		pm.makePersistent(ss);
		pm.makePersistent(tt);
		pm.makePersistent(uu);
		pm.makePersistent(vv);
		pm.makePersistent(ww);
		pm.makePersistent(xx);
		pm.makePersistent(zz);
		pm.makePersistent(aaa);
		pm.makePersistent(bbb);
		pm.makePersistent(ccc);
		pm.makePersistent(ddd);
		pm.makePersistent(eee);
		pm.makePersistent(fff);
		pm.makePersistent(ggg);
		pm.makePersistent(hhh);
		pm.makePersistent(iii);
		pm.makePersistent(jjj);
	}
	
	/**
	 * Add an OwnedStock object into the Google DataStore
	 * @param ownedStock - OwnedStock to be added
	 */
	public void insertOwnedStock( OwnedStock ownedStock )
	{
		pm.makePersistent(ownedStock);
	}
	
	/**
	 * Get a list of OwnedStocks for a particular user
	 * @param uid - ID of user to search Owned Stocks for
	 * @return - List of Owned Stocks
	 */
	public ArrayList<OwnedStock> getOwnedStocks( Long uid )
	{
		// Initialize a new list, stocks, of Owned Stocks
        ArrayList<OwnedStock> stocks = new ArrayList<OwnedStock>();
        // GQL query to get all the Owned Stocks in Google DataStore
        String query = "select from " + OwnedStock.class.getName();
        // Cast the results from GQL query into a List
        @SuppressWarnings("unchecked")
		List<OwnedStock> s = (List<OwnedStock>) pm.newQuery(query).execute();
        
        // For each Owned Stock obtained from Google DataStore
        // If Owned Stock belongs to given user, add it into stocks ArrayList
        for ( int i = 0; i < s.size(); i++ )
        {
        	if ( s.get(i).getUid().equals(uid))
        	stocks.add( s.get(i) );
        }
        // Return the ArrayList containing the stocks owned by given user
        return stocks;
	}
	
	/**
	 * Insert a Stock object (new celebrity) into the Google DataStore
	 * @param stock - Stock to be inserted
	 */
	public void insertStock( Stock stock )
	{
	    pm.makePersistent(stock);
	}
	
	/**
	 * Get a list of all the stocks in the Google DataStore
	 * @return - ArrayList of all the Stock objects in the Google DataStore
	 */
	public ArrayList<Stock> getStock()
	{		
		ArrayList<Stock> s = new ArrayList<Stock>();
        try{
        	for ( int i = 1; i <= 61; i++ )
        	{
        		s.add( pm.getObjectById(Stock.class, new Long(i) ) );
        	}
        }
        catch(JDOObjectNotFoundException e){
        	return s;
        }
        return s;
	}
	
	/**
	 * Aggregate all the stock prices to be used for a graph
	 * @return - String containing url to graph image
	 */
	public String getTotalGraph()
	{
		// Declare string to store address to chart image
		String stringPrices;
		// Retrieves list of stocks
		ArrayList<Stock> myStocks = this.getStock();
		// Variable to store current calculated total price for a period of time
		Double currTotal = 0.0;
		// Variable to store highest total stock price
		Double highPrice = 0.0;

		// Adds up prices of all stocks from earliest point in time
		for(int i=0 ; i<myStocks.size() ; i++)
		{
			currTotal += myStocks.get(i).getPriceList().get(0);
		}
		// Earliest price set as highest price by default
		highPrice = currTotal;
		// Total stock prices string initialized
		stringPrices = currTotal.toString();

		// Iterates through each of the 99 remaining stored stock prices 
		for(int i=1; i<myStocks.get(0).getPriceList().size(); i++)
		{
			// Adds up all stock prices at a certain point in time
			currTotal=0.0;
			for(int j=1 ; j<myStocks.size() ; j++)
			{
				currTotal += myStocks.get(j).getPriceList().get(i);
			}
			
			// Updates highest total stock price accordingly
			if(currTotal > highPrice)
			{
				highPrice = currTotal;
			}
			
			// Adds calculated total stock price to string
			stringPrices += "," + currTotal;	
		}

		double gridValue = (100/(highPrice)) * 10;
		// Creates a string containing address to graph image.
		String graphImage = "http://chart.apis.google.com/chart?"
		+ "chtt=Stock+History&"
		+ "cht=lc&chs=500x300&chd=t:"
		+ stringPrices + "&"
		+ "chxr=1,0," + highPrice + "&chds=0," + highPrice + "&"
		+ "chco=4d89f9&"
		+ "chxt=x,y&chxl=0:|&"
		+ "chls=3,1,0&"
		+ "chg=0," + gridValue + ",5,5";
		
		return graphImage;
	}
	
	/**
	 * Get a List of all the Stocks in the Google DataStore sorted by names alphabetically
	 * @return - list of all the Stocks in Google DataStore sorted alphabetically
	 */
	public ArrayList<Stock> getStockSQL()
	{
		// Initilize ArrayList of Stocks
		ArrayList<Stock> stocks = new ArrayList<Stock>();
		// GQL query to get all Stocks ordered alphabetically 
        String query = "select from " + Stock.class.getName() + " order by name";
        // Cast returned object into List of Stocks
		@SuppressWarnings("unchecked")
		List<Stock> s = (List<Stock>) pm.newQuery(query).execute();
        // Put all Stock objects into ArrayList to be returned
        for ( int i = 0; i < s.size(); i++ )
        {
        	stocks.add( s.get(i) );
        }
        return stocks;
	}
	
	/**
	 * Get Stock with given Stock ID
	 * @param id - ID of stock to retrieve from Google DataStore
	 * @return - Stock object
	 */
	public Stock getStock( Long id )
	{		
		try{
			return pm.getObjectById(Stock.class, id);
		}
		catch (JDOObjectNotFoundException e){
			return null;
		}
	}
	
	/**
	 * Close the PersistanceManager
	 */
	public void close()
	{
		pm.close();
	}
	
	/**
	 * Insert new User into Google DataStore
	 * @param user - new User to be inserted
	 */
	public void insertUser( User user)
	{
		pm.makePersistent(user);
	}
	
	/**
	 * Get a particular User from Google DataStore
	 * @param uid - ID of User to retrieve
	 * @return - User
	 */
	public User getUser( Long uid )
	{
		try{
			return pm.getObjectById(User.class, uid);
		}
		catch (JDOObjectNotFoundException e){
			return null;
		}
	}
	
	/**
	 * Get all the Users from Google DataStore
	 * @return - ArrayList of all the Users
	 */
	public ArrayList<User> getUser()
	{
		// Initilize ArrayList to be returned later
        ArrayList<User> users = new ArrayList<User>();
        // GQL query
        String query = "select from " + User.class.getName();
        // Cast returned object into List of Users
        @SuppressWarnings("unchecked")
		List<User> u = (List<User>) pm.newQuery(query).execute();
        // Add all the Users into ArrayList to be returned
        for ( int i = 0; i < u.size(); i++ )
        {
        	users.add( u.get(i) );
        }
        return users;
	}
	
	/**
	 * User purchases shares of a stock
	 * @param user - User to purchase shares
	 * @param id - ID of stock to purchase
	 * @param quantity - number of shares to purchase
	 * @param purchasePrice - price per share
	 * @return - true if successful, false otherwise
	 */
	public boolean buyStock( User user, Long id, int quantity, double purchasePrice )
	{
		// User's starting balance
		double oldBalance = user.getBalance();
		// Check to make sure user has enough money and quantity being purchased is greater than 0
		if( oldBalance-(quantity*purchasePrice) >= 0 && quantity>0)
		{
			// Update User's balance
			user.setBalance( oldBalance - (purchasePrice*quantity));
			// Create new OwnedStock object
			OwnedStock ownedStock = new OwnedStock( id, user.getUserID(),quantity, purchasePrice );
			// Add OwnedStock object into Google DataStore
			pm.makePersistent(ownedStock);
			return true;
		}
		return false;
	}
	
	/**
	 * Check if the stocks in the Google DataStore are initialized
	 * @return - true if already initialized, false otherwise
	 */
	public boolean isInitialized(){
        ArrayList<Stock> s = new ArrayList<Stock>();
        try{
        	for ( int i = 1; i <= 50; i++ )
        	{
        		s.add( pm.getObjectById(Stock.class, new Long(i) ) );
        	}
        	return true;
        }
        catch(JDOObjectNotFoundException e){
        	return false;
        }
	}
	
	/**
	 * Return instance of PersistenceManager
	 * @return - PersistenceManager
	 */
	public 	PersistenceManager getPM()
	{
		return pm;
	}
	
	/**
	 * Compute asset value of user
	 * @param user - User to computer asset value for
	 */
	public void computeAssetValue( User user )
	{
		// Get ArrayList of all the OwnedStocks belonging to given user
		ArrayList<OwnedStock> stocks = getOwnedStocks( user.getUserID() );
		// Set asset value to 0
		double assets = 0;
		// Add user's balance to their asset value
		assets += user.getBalance();
		// If user has no OwnedStocks, asset value is just equal to their balance
		if ( stocks == null )
			user.setAssetValue(assets);
		// If user has OwnedStocks, add the value of their OwnedStocks to their assets
		else
		{
			for( int i=0; i<stocks.size(); i++)
			{
				double totalValue = getStock((stocks.get(i).getID())).getCurrentPrice() * stocks.get(i).getQuantity();
				assets += totalValue;
			}
			user.setAssetValue(assets);
		}
	}
	
	/**
	 * Delete OwnedStock object in Google DataStore
	 * @param ownedStock - OwnedStock to be deleted
	 */
	public void deleteOwnedStock( OwnedStock ownedStock )
	{
		pm.deletePersistent(ownedStock);
	}
	
	public void updateStocksAndPort()
	{
		DecimalFormat twoDForm = new DecimalFormat("#.##");
		ArrayList<Stock> stocks = getStock();
		int score;
		int num;

		for(int i=0; i < 20;i++){
			num = 1+ (new Random()).nextInt(61);
			score=0;
			double newPrice=0;		

			
			score = TweetCounter.getCount(stocks.get(num).getName());	
			System.out.println("Score for one person Done!" + score);
			
			
			//score=40;
			
			newPrice=stocks.get(num).getCurrentPrice() + ((score*0.75 - stocks.get(num).getCurrentPrice())/100);
			newPrice = Double.valueOf(twoDForm.format(newPrice));
			stocks.get(num).updatePrice(newPrice);
			
			//ds.updateStock(stocks.get(i));
		}
		
	
//			ArrayList<User> users = getUser();
//			for ( int i = 0; i < users.size(); i++ )
//				computeAssetValue( users.get(i) );
				
		

	}

}
